/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

#ifndef __FLGR_CORE_TRANSFORM_FAST_UTIL_H
#define __FLGR_CORE_TRANSFORM_FAST_UTIL_H
 

/*
  Use SSE instructions
  Get Row r1,r2,r3,r4,r5,r6,r7,r8 and do transposition
  Transposed Matrix Row are ordered as follow :
  r8,r4,r6,r2,r7,r3,r5,r1
*/
#define FLGR_MACRO_TRANSPOSE_BLOCK_8x8_BYTE(tmp, r1,r2,r3,r4,r5,r6,r7,r8) \
  /*FIRST STEP GROUP Byte To Word*/					\
  tmp1 = _m_punpckhbw(r1,r2);						\
  r2  = _m_punpcklbw(r1,r2);						\
  r1 = tmp1;								\
									\
  tmp1 = _m_punpckhbw(r3,r4);						\
  r4  = _m_punpcklbw(r3,r4);						\
  r3 = tmp1;								\
									\
  tmp1 = _m_punpckhbw(r5,r6);						\
  r6  = _m_punpcklbw(r5,r6);						\
  r5 = tmp1;								\
									\
  tmp1 = _m_punpckhbw(r7,r8);						\
  r8  = _m_punpcklbw(r7,r8);						\
  r7 = tmp1;								\
									\
  /*SECOND STEP GROUP Word to DWord*/					\
  tmp1 = _m_punpckhwd(r1,r3);						\
  r3  = _m_punpcklwd(r1,r3);						\
  r1 = tmp1;								\
									\
  tmp1 = _m_punpckhwd(r2,r4);						\
  r4  = _m_punpcklwd(r2,r4);						\
  r2 = tmp1;								\
									\
  tmp1 = _m_punpckhwd(r5,r7);						\
  r7  = _m_punpcklwd(r5,r7);						\
  r5 = tmp1;								\
									\
  tmp1 = _m_punpckhwd(r6,r8);						\
  r8  = _m_punpcklwd(r6,r8);						\
  r6 = tmp1;								\
									\
  /*THIRD STEP GROUP DWord to QWord */					\
  tmp1 = _m_punpckhdq(r1,r5);						\
  r5  = _m_punpckldq(r1,r5);						\
  r1 = tmp1;								\
									\
  tmp1 = _m_punpckhdq(r3,r7);						\
  r7  = _m_punpckldq(r3,r7);						\
  r3 = tmp1;								\
									\
  tmp1 = _m_punpckhdq(r2,r6);						\
  r6  = _m_punpckldq(r2,r6);						\
  r2 = tmp1;								\
									\
  tmp1 = _m_punpckhdq(r4,r8);						\
  r8  = _m_punpckldq(r4,r8);						\
  r4 = tmp1;								\



#define PUNPCKHBW(a,b) _mm_unpackhi_epi8(a,b)
#define PUNPCKLBW(a,b) _mm_unpacklo_epi8(a,b)

#define PUNPCKHWD(a,b) _mm_unpackhi_epi16(a,b)
#define PUNPCKLWD(a,b) _mm_unpacklo_epi16(a,b)

#define PUNPCKHDQ(a,b) _mm_unpackhi_epi32(a,b)
#define PUNPCKLDQ(a,b) _mm_unpacklo_epi32(a,b)

#define PUNPCKHQDQ(a,b) _mm_unpackhi_epi64(a,b)
#define PUNPCKLQDQ(a,b) _mm_unpacklo_epi64(a,b)



/*
  Use SSE2 instructions
  Get Row r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16 and do transposition
  Transposed Matrix Row are ordered as follow :
  r16,r8,r12,r4,r14,r6,r10,r2,r15,r7,r11,r3,r13,r5,r9,r1
*/

#define FLGR_MACRO_TRANSPOSE_BLOCK_16x16_BYTE(r1,r2,r3,r4,r5,r6,r7,r8,	\
					      r9,r10,r11,r12,r13,r14,r15,r16,tmp1) \
  /*FIRST STEP GROUP Byte To Word*/					\
  tmp1 = PUNPCKHBW(r1,r2);						\
  r2  = PUNPCKLBW(r1,r2);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r3,r4);						\
  r4  = PUNPCKLBW(r3,r4);						\
  r3 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r5,r6);						\
  r6  = PUNPCKLBW(r5,r6);						\
  r5 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r7,r8);						\
  r8  = PUNPCKLBW(r7,r8);						\
  r7 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r9,r10);						\
  r10 = PUNPCKLBW(r9,r10);						\
  r9 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r11,r12);						\
  r12 = PUNPCKLBW(r11,r12);						\
  r11 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r13,r14);						\
  r14 = PUNPCKLBW(r13,r14);						\
  r13 = tmp1;								\
									\
  tmp1 = PUNPCKHBW(r15,r16);						\
  r16 = PUNPCKLBW(r15,r16);						\
  r15 = tmp1;								\
									\
  /*SECOND STEP GROUP Word to DWord*/					\
  tmp1 = PUNPCKHWD(r1,r3);						\
  r3  = PUNPCKLWD(r1,r3);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r2,r4);						\
  r4  = PUNPCKLWD(r2,r4);						\
  r2 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r5,r7);						\
  r7  = PUNPCKLWD(r5,r7);						\
  r5 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r6,r8);						\
  r8  = PUNPCKLWD(r6,r8);						\
  r6 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r9,r11);						\
  r11  = PUNPCKLWD(r9,r11);						\
  r9 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r10,r12);						\
  r12  = PUNPCKLWD(r10,r12);						\
  r10 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r13,r15);						\
  r15  = PUNPCKLWD(r13,r15);						\
  r13 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r14,r16);						\
  r16  = PUNPCKLWD(r14,r16);						\
  r14 = tmp1;								\
									\
  /*THIRD STEP GROUP DWord to QWord */					\
  tmp1 = PUNPCKHDQ(r1,r5);						\
  r5  = PUNPCKLDQ(r1,r5);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r2,r6);						\
  r6  = PUNPCKLDQ(r2,r6);						\
  r2 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r3,r7);						\
  r7  = PUNPCKLDQ(r3,r7);						\
  r3 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r4,r8);						\
  r8  = PUNPCKLDQ(r4,r8);						\
  r4 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r9,r13);						\
  r13  = PUNPCKLDQ(r9,r13);						\
  r9 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r10,r14);						\
  r14  = PUNPCKLDQ(r10,r14);						\
  r10 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r11,r15);						\
  r15  = PUNPCKLDQ(r11,r15);						\
  r11 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r12,r16);						\
  r16  = PUNPCKLDQ(r12,r16);						\
  r12 = tmp1;								\
									\
  /*FOURTH STEP GROUP QWord to DQWord */				\
  tmp1 = PUNPCKHQDQ(r1,r9);						\
  r9  = PUNPCKLQDQ(r1,r9);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r2,r10);						\
  r10  = PUNPCKLQDQ(r2,r10);						\
  r2 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r3,r11);						\
  r11  = PUNPCKLQDQ(r3,r11);						\
  r3 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r4,r12);						\
  r12  = PUNPCKLQDQ(r4,r12);						\
  r4 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r5,r13);						\
  r13  = PUNPCKLQDQ(r5,r13);						\
  r5 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r6,r14);						\
  r14  = PUNPCKLQDQ(r6,r14);						\
  r6 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r7,r15);						\
  r15  = PUNPCKLQDQ(r7,r15);						\
  r7 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r8,r16);						\
  r16  = PUNPCKLQDQ(r8,r16);						\
  r8 = tmp1
  


/*
  Get Row r1,r2,r3,r4,r5,r6,r7,r8 and do transposition
  Transposed Matrix Row are ordered as follow :
  r8,r4,r6,r2,r7,r3,r5,r1
*/
#define FLGR_MACRO_TRANSPOSE_BLOCK_8x8_WORD(r1,r2,r3,r4,r5,r6,r7,r8, tmp1) \
  /*FIRST STEP GROUP Word To DWord*/					\
  tmp1 = PUNPCKHWD(r1,r2);						\
  r2  = PUNPCKLWD(r1,r2);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r3,r4);						\
  r4  = PUNPCKLWD(r3,r4);						\
  r3 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r5,r6);						\
  r6  = PUNPCKLWD(r5,r6);						\
  r5 = tmp1;								\
									\
  tmp1 = PUNPCKHWD(r7,r8);						\
  r8  = PUNPCKLWD(r7,r8);						\
  r7 = tmp1;								\
									\
  /*SECOND STEP GROUP DWord to QWord*/					\
  tmp1 = PUNPCKHDQ(r1,r3);						\
  r3  = PUNPCKLDQ(r1,r3);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r2,r4);						\
  r4  = PUNPCKLDQ(r2,r4);						\
  r2 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r5,r7);						\
  r7  = PUNPCKLDQ(r5,r7);						\
  r5 = tmp1;								\
									\
  tmp1 = PUNPCKHDQ(r6,r8);						\
  r8  = PUNPCKLDQ(r6,r8);						\
  r6 = tmp1;								\
									\
  /*THIRD STEP GROUP QWord to DQWord */					\
  tmp1 = PUNPCKHQDQ(r1,r5);						\
  r5  = PUNPCKLQDQ(r1,r5);						\
  r1 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r3,r7);						\
  r7  = PUNPCKLQDQ(r3,r7);						\
  r3 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r2,r6);						\
  r6  = PUNPCKLQDQ(r2,r6);						\
  r2 = tmp1;								\
									\
  tmp1 = PUNPCKHQDQ(r4,r8);						\
  r8  = PUNPCKLQDQ(r4,r8);						\
  r4 = tmp1						

/*
  Get Row r1,r2,r3,r4,r5,r6,r7,r8 and do transposition
  Transposed Matrix Row are ordered as follow :
  r8,r4,r6,r2,r7,r3,r5,r1
*/
#define FLGR_MACRO_TRANSPOSE_BLOCK_4x4_DWORD(r1,r2,r3,r4,tmp1)	\
  /*FIRST STEP GROUP Word To DWord*/				\
  tmp1 = PUNPCKHDQ(r1,r2);					\
  r2  = PUNPCKLDQ(r1,r2);					\
  r1 = tmp1;							\
								\
  tmp1 = PUNPCKHDQ(r3,r4);					\
  r4  = PUNPCKLDQ(r3,r4);					\
  r3 = tmp1;							\
								\
  /*SECOND STEP GROUP DWord to QWord*/				\
  tmp1 = PUNPCKHQDQ(r1,r3);					\
  r3  = PUNPCKLQDQ(r1,r3);					\
  r1 = tmp1;							\
								\
  tmp1 = PUNPCKHQDQ(r2,r4);					\
  r4  = PUNPCKLQDQ(r2,r4);					\
  r2 = tmp1



#endif

#ifdef __cplusplus
}
#endif
